/**
 * Classe modélisant la table des symboles de compilation
 * 
 * @author BlobbyCompiloTeam
 *
 */


import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;


public class TabIdent implements GramConstants{
	
	private HashMap<String,Ident> globaux; // La table des symboles globaux
	private HashMap<String,Ident> locaux; // La table des symboles locaux
	
	/**
	 * Constructeur de la classe
	 * @param taille la taille initiale que l'on donne aux tables des locaux et globaux
	 */
	public TabIdent(int taille) {
		globaux = new HashMap<String,Ident>(taille);
		locaux = new HashMap<String,Ident>(taille);
	}
	
	
	/**
	 * Cherche dans la table des globaux la structure Ident correspondant à la clé passé en paramètre
	 * @param cle le nom du symbole duquel on souhaite récupérer l'identifiant
	 * @return Ident l'identifiant correspondant au nom du symbole. Null si non trouvé.
	 */
	public Ident chercheIdentGlobaux(String cle) {
		return (Ident) globaux.get(cle);
	}
	

	/**
	 * Cherche dans la table des locaux la structure Ident correspondant à la clé passé en paramètre
	 * @param cle le nom du symbole duquel on souhaite récupérer l'identifiant
	 * @return Ident l'identifiant correspondant au nom du symbole. Null si non trouvé.
	 */
	public Ident chercheIdentLocaux(String cle) {
		return (Ident) locaux.get(cle);
	}
	
	
	/**
	 * Teste l'existence du symbole nommé en paramètre dans la table des globaux
	 * @param cle le nom du symbole duquel on souhaite tester l'existence
	 * @return boolean Vrai s'il existe dans la table des globaux, Faux sinon
	 */
	public boolean existeIdentGlobaux(String cle) {
		return globaux.containsKey(cle);
	}
	
	/**
	 * Teste l'existence du symbole nommé en paramètre dans la table des locaux
	 * @param cle le nom du symbole duquel on souhaite tester l'existence
	 * @return boolean Vrai s'il existe dans la table des locaux, Faux sinon
	 */
	public boolean existeIdentLocaux(String cle) {
		return locaux.containsKey(cle);
	}
	
	/**
	 * Ajoute un symbole dans la table des globaux. Affiche une erreur si le nom du symbole existe déjà.
	 * @param cle le nom du symbole
	 * @param id référence vers la structure Ident correspondant à ce symbole
	 */
	public void rangeIdentGlobaux(String cle, Ident id) {
		if(globaux.containsKey(cle))
		{
			MsgErreur.getErreur(Gram.token.beginLine, "TabIdent.rangeIdentGlobaux", "variable " + cle +" déjà déclarée");
		}
		else
		{
			globaux.put(cle, id);
		}
	}
	
	/**
	 * Ajoute un symbole dans la table des locaux. Affiche une erreur si le nom du symbole existe déjà.
	 * @param cle le nom du symbole
	 * @param id référence vers la structure Ident correspondant à ce symbole
	 */
	public void rangeIdentLocaux(String cle, Ident id)
	{
		if(locaux.containsKey(cle))
		{
			MsgErreur.getErreur(Gram.token.beginLine, "TabIdent.rangeIdentLocaux", "variable " + cle +" déjà déclarée");
		}
		else
		{
			locaux.put(cle, id);
		}
	}
	
	/**
	 * Calcule pour chaque Ident son offset dans la pile des locaux, et stocke le résultat dans la structure Ident.
	 * 
	 * @param taillePara la taille totale des variables locales
	 */
	public void calculOffsetLocaux(int taillePara)
	{
		Set<String> clelocaux = locaux.keySet();
		Iterator<String> iter = clelocaux.iterator();
		while (iter.hasNext()){
			String cle = iter.next();
			Ident id = locaux.get(cle);
			
			if (id.getNature() == natPara){
				int offset = taillePara + 4 - (((IdPara)id).getOffset()*2);
				((IdPara)id).setOffset(offset);
			}
		}
	}
	
	
	/**
	 * Vide la table des locaux en fin de fonction.
	 */
	public void videLocaux()
	{
		locaux.clear();
	}
	
	/**
	 * Permet de calculer de la taille de la table des locaux
	 * @return la taille des locaux
	 */
	public int sizeLocaux(){
		return locaux.size();
	}
	
}